package com.xs.designpattern;

import lombok.extern.slf4j.Slf4j;

import java.util.Deque;
import java.util.LinkedList;

/**
 * 巫师类 持有两个栈用于记录执行的法术操作和撤销的法术操作
 *
 * @author xs
 */
@Slf4j
public class Wizard {
    /**
     * 使用双端队列记录执行的法术操作
     */
    private final Deque<Runnable> undoStack = new LinkedList<>();
    /**
     * 使用双端队列记录执行的撤销的法术操作
     */
    private final Deque<Runnable> redoStack = new LinkedList<>();

    /**
     * 施放法术操作，同时记录到撤销栈中
     *
     * @param runnable runnable
     */
    public void castSpell(Runnable runnable) {
        runnable.run();
        //在此双端队列的末尾插入指定元素
        undoStack.offerLast(runnable);
    }

    /**
     * 撤销上一个法术操作，将操作从撤销栈移到重做栈
     */
    public void undoLastSpell() {
        //想撤销上一个法术操作，需要先判断执行记录的队列中是否有记录存在，有则进入if内部，没有则不做操作
        if (!undoStack.isEmpty()) {
            //删除执行队列中的最后一个元素
            Runnable previousSpell = undoStack.pollLast();
            //添加到撤销队列中
            redoStack.offerLast(previousSpell);
            previousSpell.run();
        }
    }

    /**
     * 重做上一个撤销的法术操作，将操作从重做栈移到撤销栈
     */
    public void redoLastSpell() {
        //想重做最后一个咒语需要先判断撤销队列是否有撤销的操作记录，有则进入if内部，没有不做操作
        if (!redoStack.isEmpty()) {
            //删除撤销队列中的最后一个操作
            Runnable previousSpell = redoStack.pollLast();
            //添加到执行队列中
            undoStack.offerLast(previousSpell);
            previousSpell.run();
        }
    }
}
